#ifndef __MODULE_MANAGER__
#define __MODULE_MANAGER__

#include <map>
#include <string>
#include "view.h"

namespace xm
{

	class mod_mgr_t
	{
	protected:

		typedef std::map< std::string, optr<image_view_t> >	mod_map_t;

		mod_map_t	_modules;

	public:

		enum 
		{
			COND_HAS_TLS	= 1,
			COND_HAS_ENTRY	 = 2,
		};

		size_t get_module_count()
		{
			return _modules.size();
		}

		long fetch_modules( std::vector< optr<image_view_t> > & vec, size_t condition )
		{
			mod_map_t::iterator it = _modules.begin();
			for( ; it != _modules.end(); ++ it )
			{
				optr<image_view_t> imgv = it->second;
				if( condition & COND_HAS_TLS )
				{
					if( !imgv->image_object()->tls_rva() )
						continue;
				}
				if( condition & COND_HAS_ENTRY )
				{
					if( !imgv->image_object()->entry_point() )
						continue;
				}
				vec.push_back( it->second );
			}
			return S_OK;
		}

		void on_module_load( image_view_t * imgo )
		{
			if( !imgo ) return ;
			optr<volm_file_t> fo = imgo->section->get_data_file();
			if( !fo ) return ;
			std::string full;
			fo->get_win32_full_path(full);
			_modules[full] = imgo;
		}

		void on_module_unload( image_view_t * imgo )
		{
			optr<volm_file_t> fo = imgo->section->get_data_file();
			if( !fo ) return ;
			std::string full;
			fo->get_win32_full_path(full);
			_modules.erase( full );
		}

		optr<image_view_t> find_module( std::string & full )
		{
			mod_map_t::iterator it = _modules.find( full );
			if( it == _modules.end() ) return NULL;
			return it->second;
		}

		optr<image_view_t> find_prev_module( vxvma_t cur_vma )
		{
			mod_map_t::iterator it = _modules.begin();
			mod_map_t::iterator hit = _modules.end();
			uint64_t dist = -1;
			for( ; it != _modules.end(); ++ it )
			{
				optr<image_view_t> img2 = it->second;
				if( img2->stand.base >= cur_vma ) 
					continue;
				uint64_t this_dist = cur_vma - img2->stand.base;
				if( this_dist >= dist )
					continue;
				dist = this_dist;
				hit = it;
			}
			
			if( hit == _modules.end() )
				return NULL;

			return hit->second;
		}

	};


		
};


#endif